package com.yqw.onlineDocs.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yqw.onlineDocs.common.ErrorCode;
import com.yqw.onlineDocs.constant.CommonConstant;
import com.yqw.onlineDocs.exception.ThrowUtils;
import com.yqw.onlineDocs.mapper.DocumentMapper;
import com.yqw.onlineDocs.model.dto.document.DocumentQueryRequest;
import com.yqw.onlineDocs.model.entity.Document;
import com.yqw.onlineDocs.model.entity.User;
import com.yqw.onlineDocs.model.vo.DocumentVO;
import com.yqw.onlineDocs.model.vo.UserVO;
import com.yqw.onlineDocs.manager.AiManager;
import com.yqw.onlineDocs.service.DocumentService;
import com.yqw.onlineDocs.service.UserService;
import com.yqw.onlineDocs.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 文档服务实现
 *
 */
@Service
@Slf4j
public class DocumentServiceImpl extends ServiceImpl<DocumentMapper, Document> implements DocumentService {

  @Resource
  private UserService userService;
  
  @Resource
  private AiManager aiManager;

  /**
   * 校验数据
   *
   * @param document
   * @param add      对创建的数据进行校验
   */
  @Override
  public void validDocument(Document document, boolean add) {
    ThrowUtils.throwIf(document == null, ErrorCode.PARAMS_ERROR);
    String title = document.getTitle();
    String content = document.getContent();
    // 创建数据时，参数不能为空
    if (add) {
      ThrowUtils.throwIf(StringUtils.isBlank(title), ErrorCode.PARAMS_ERROR, "标题不能为空");
      ThrowUtils.throwIf(StringUtils.isBlank(content), ErrorCode.PARAMS_ERROR, "内容不能为空");
    }
    // 修改数据时，有参数则校验
    if (StringUtils.isNotBlank(title)) {
      ThrowUtils.throwIf(title.length() > 80, ErrorCode.PARAMS_ERROR, "标题长度不能超过80个字符");
      ThrowUtils.throwIf(title.length() < 2, ErrorCode.PARAMS_ERROR, "标题长度不能少于2个字符");
    }
    if (StringUtils.isNotBlank(content)) {
      ThrowUtils.throwIf(content.length() > 10000, ErrorCode.PARAMS_ERROR, "内容长度不能超过10000个字符");
    }
  }

  /**
   * 获取查询条件
   *
   * @param documentQueryRequest
   * @return
   */
  @Override
  public QueryWrapper<Document> getQueryWrapper(DocumentQueryRequest documentQueryRequest) {
    QueryWrapper<Document> queryWrapper = new QueryWrapper<>();
    if (documentQueryRequest == null) {
      return queryWrapper;
    }
    // todo 从对象中取值
    Long id = documentQueryRequest.getId();
    String title = documentQueryRequest.getTitle();
    String content = documentQueryRequest.getContent();
    String cover = documentQueryRequest.getCover();
    Integer status = documentQueryRequest.getStatus();
    Long userId = documentQueryRequest.getUserId();
    String sortField = documentQueryRequest.getSortField();
    String sortOrder = documentQueryRequest.getSortOrder();
    // todo 补充需要的查询条件
    // 模糊查询
    queryWrapper.like(StringUtils.isNotBlank(title), "title", title);
    queryWrapper.like(ObjectUtils.isNotEmpty(status), "status", status);
    queryWrapper.like(StringUtils.isNotBlank(content), "content", content);
    // 精确查询
    queryWrapper.ne(ObjectUtils.isNotEmpty(cover), "cover", cover);
    queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
    queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
    // 排序规则
    queryWrapper.orderBy(SqlUtils.validSortField(sortField),
        sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
        sortField);
    return queryWrapper;
  }

  /**
   * 获取文档封装
   *
   * @param document
   * @param request
   * @return
   */
  @Override
  public DocumentVO getDocumentVO(Document document, HttpServletRequest request) {
    // 对象转封装类
    DocumentVO documentVO = DocumentVO.objToVo(document);

    // todo 可以根据需要为封装对象补充值，不需要的内容可以删除
    // region 可选
    // 1. 关联查询用户信息
    Long userId = document.getUserId();
    User user = null;
    if (userId != null && userId > 0) {
      user = userService.getById(userId);
    }
    UserVO userVO = userService.getUserVO(user);
    documentVO.setUser(userVO);
    // endregion

    return documentVO;
  }

  /**
   * 分页获取文档封装
   *
   * @param documentPage
   * @param request
   * @return
   */
  @Override
  public Page<DocumentVO> getDocumentVOPage(Page<Document> documentPage, HttpServletRequest request) {
    List<Document> documentList = documentPage.getRecords();
    Page<DocumentVO> documentVOPage = new Page<>(documentPage.getCurrent(), documentPage.getSize(),
        documentPage.getTotal());
    if (CollUtil.isEmpty(documentList)) {
      return documentVOPage;
    }
    // 对象列表 => 封装对象列表
    List<DocumentVO> documentVOList = documentList.stream().map(document -> {
      return DocumentVO.objToVo(document);
    }).collect(Collectors.toList());

    // todo 可以根据需要为封装对象补充值，不需要的内容可以删除
    // region 可选
    // 1. 关联查询用户信息
    Set<Long> userIdSet = documentList.stream().map(Document::getUserId).collect(Collectors.toSet());
    Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
        .collect(Collectors.groupingBy(User::getId));
    // endregion

    documentVOPage.setRecords(documentVOList);
    return documentVOPage;
  }

  /**
   * 使用AI生成文档内容
   *
   * @param prompt 用户提示词
   * @param loginUser 当前登录用户
   * @return 生成的文档内容
   */
  @Override
  public String generateDocumentContentByAi(String prompt, User loginUser) {
    // 系统提示词（简洁版）
    String systemPrompt = """
      作为文档生成助手，你需要：
      1. 生成Markdown格式文档
      2. 包含标题、正文、总结三部分
      3. 回答字数不超过600字
      3. 避免敏感内容
    """;
    // 构建用户提示词，包含用户的原始提示
    String userPrompt = "请根据以下要求生成一篇文档：" + prompt;
    // 调用AI服务生成内容
    String generatedContent = aiManager.doChar(systemPrompt, userPrompt);
    // 记录日志
    log.info("用户 {} 使用AI生成了文档内容，提示词：{}", loginUser.getUserAccount(), prompt);
    return generatedContent;
  }

}
